﻿using Microsoft.AspNet.Identity;
using Sidvall.IdentityManager.Security.Entities;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Sidvall.IdentityManager.Security
{
    public class IdentityUserManager : UserManager<AspNetUsers>
    {
        #region Public Members

        #region Create

        public static IdentityUserManager Create()
        {
            var manager = new IdentityUserManager(new UserStore())
            {
                // Configure validation logic for passwords
                PasswordValidator = new PasswordValidator
                {
                    RequiredLength = 1,
                    RequireNonLetterOrDigit = false,
                    RequireDigit = false,
                    RequireLowercase = false,
                    RequireUppercase = false,
                },

                // Configure user lockout defaults
                UserLockoutEnabledByDefault = true,
                DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5),
                MaxFailedAccessAttemptsBeforeLockout = 5,

                EmailService = new EmailService(),
                SmsService = new SmsService(),
                UserTokenProvider = new UserTokenProvider(),
            };

            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<AspNetUsers>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true,
            };

            // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
            manager.RegisterTwoFactorProvider(Sidvall.Security.TwoFactorProvider.Sms.ToString(), new PhoneNumberTokenProvider
            {
                MessageFormat = "Your security code is {0}"
            });
            manager.RegisterTwoFactorProvider(Sidvall.Security.TwoFactorProvider.Email.ToString(), new EmailTokenProvider
            {
                Subject = "Security Code",
                BodyFormat = "Your security code is {0}"
            });
            return manager;
        }

        #endregion
        #region CreateIdentityAsync

        public override Task<System.Security.Claims.ClaimsIdentity> CreateIdentityAsync(AspNetUsers user, string authenticationType)
        {
            System.Security.Claims.Claim claim;

            var claims = new List<System.Security.Claims.Claim>();
            if (user.AspNetUserClaims != null)
            {
                foreach (var item in user.AspNetUserClaims.Items)
                {
                    claim = new System.Security.Claims.Claim(item.ClaimType, item.ClaimValue);
                    claims.Add(claim);
                }
            }
            claim = new System.Security.Claims.Claim(Sidvall.Security.ClaimTypes.Subject, user.Id);
            claims.Add(claim);
            if (!string.IsNullOrWhiteSpace(user.Email))
            {
                claim = new System.Security.Claims.Claim(Sidvall.Security.ClaimTypes.Email, user.Email);
                claims.Add(claim);
                claim = new System.Security.Claims.Claim(Sidvall.Security.ClaimTypes.EmailVerified, user.EmailConfirmed.ToString());
                claims.Add(claim);
            }
            if (!string.IsNullOrWhiteSpace(user.PhoneNumber))
            {
                claim = new System.Security.Claims.Claim(Sidvall.Security.ClaimTypes.PhoneNumber, user.PhoneNumber);
                claims.Add(claim);
                claim = new System.Security.Claims.Claim(Sidvall.Security.ClaimTypes.PhoneNumberVerified, user.PhoneNumberConfirmed.ToString());
                claims.Add(claim);
            }
            return Task.FromResult(new System.Security.Claims.ClaimsIdentity(claims, authenticationType, Sidvall.Security.ClaimTypes.Name, Sidvall.Security.ClaimTypes.Role));
        }

        #endregion

        #endregion
        #region Constructors

        public IdentityUserManager(IUserStore<AspNetUsers> store)
            : base(store)
        {
        }

        #endregion
    }
}
